<?php
namespace api\modules\v1\models;

use api\components\ApiModel;
use api\components\RuleUtil;
use common\models\ARAssets;
use common\models\ARBrokerAmount;
use common\models\ARBrokerScoring;
use common\models\ARCoinType;
use common\models\AROrder;
use common\models\ARTrustBroker;
use common\models\ARUser;
use common\models\ARUserCertificate;
use Yii;
use yii\helpers\ArrayHelper;

/**
 * 经纪人模型
 * @author CGA
 */
class Broker extends ApiModel
{
    const SCENARIO_APPLY = 'apply';
    const SCENARIO_QUERY_AMOUNT = 'query_amount';
    const SCENARIO_SETAMOUNT = 'setamount';
    const SCENARIO_LIST = 'list';
    const SCENARIO_RECEIVE_MONEY = 'receive_money';
    const SCENARIO_REMITTANCE = 'remittance';
    const SCENARIO_TRUST_LIST = 'trust_list';
    const SCENARIO_TRUST_ADD = 'trust_add';
    const SCENARIO_TRUST_DELETE = 'trust_delete';
    const SCENARIO_TRUST_UPDATE = 'trust_update';

    //排序字段
    const SORT_FIELD = [
        1 => 'num_now', //成交笔数
        2 => 'amount_total', //成交额
        3 => 'rating', //好评度
        4 => 'amount_remain', //经纪额度
    ];

    public $coin;
    public $amount;
    public $nickname;
    public $account;
    public $sort;
    public $sort_type;
    public $page;
    public $size;
    public $order_id;
    public $broker_id;
    public $trust_id;
    public $epithet;
    public $country;
    public $province;

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'coin'      => '币种',
            'amount'    => '数额',
            'nickname'  => '昵称',
            'account'   => '账号',
            'sort'      => '排序字段',
            'sort_type' => '排序方式',
            'page'      => '当前页',
            'size'      => '每页记录数',
            'order_id'  => '订单编号',
            'broker_id' => '经纪人编号',
            'trust_id'  => '信任经纪人编号',
            'epithet'   => '标签',
            'country'   => '国家',
            'province'  => '地区',
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        return [
            self::SCENARIO_SETAMOUNT     => ['coin', 'amount'],
            self::SCENARIO_QUERY_AMOUNT  => ['coin'],
            self::SCENARIO_LIST          => ['coin', 'amount', 'nickname', 'account', 'sort', 'sort_type', 'country', 'province', 'page', 'size'],
            self::SCENARIO_RECEIVE_MONEY => ['order_id'],
            self::SCENARIO_REMITTANCE    => ['order_id'],
            self::SCENARIO_TRUST_LIST    => ['coin', 'amount', 'nickname', 'account', 'sort', 'sort_type', 'country', 'province', 'page', 'size'],
            self::SCENARIO_TRUST_ADD     => ['broker_id', 'epithet'],
            self::SCENARIO_TRUST_DELETE  => ['trust_id'],
            self::SCENARIO_TRUST_UPDATE  => ['trust_id', 'epithet'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['coin', 'amount', 'order_id', 'broker_id', 'trust_id'], 'trim'],
            [['coin', 'amount'], 'required', 'on' => [self::SCENARIO_SETAMOUNT, self::SCENARIO_QUERY_AMOUNT]],
            ['coin', 'required', 'on' => [self::SCENARIO_LIST, self::SCENARIO_TRUST_LIST]],
            [['order_id', 'broker_id', 'trust_id'], 'required'],
            ['coin', 'in', 'range' => ARCoinType::find()->where(['status' => ARCoinType::STATUS_ACTIVE])->select('id')->asArray()->column()],
            [['amount', 'page', 'size'], 'number'],
            ['sort', 'in', 'range' => array_keys(self::SORT_FIELD)],
            ['sort', 'default', 'value' => 3],
            ['sort_type', 'in', 'range' => [SORT_DESC, SORT_ASC]], //对应3，4
            ['sort_type', 'default', 'value' => SORT_DESC],
            ['page', 'default', 'value' => 1],
            ['size', 'default', 'value' => 10],
            ['epithet', 'string', 'max' => 255],
            ['country', 'filter', 'filter' => function ($model) {
                if ($this->country) {
                    list($flag, $data) = RuleUtil::checkCountry($this->country);
                    if (!$flag) {
                        self::throwError(null, $data);
                    }
                }
                return strtoupper($this->country);
            }],
            ['province', 'filter', 'filter' => function ($model) {
                if (!$this->country || $this->country != 'CN' || $this->province == null) {
                    return null;
                } else {
                    list($flag, $data) = RuleUtil::checkProvince($this->province);
                    if (!$flag) {
                        self::throwError(null, $data);
                    }
                    return $this->province;
                }
            }],
        ];
    }

    /**
     * 申请成为经纪人
     */
    public function applyToBroker()
    {
        $uid = Yii::$app->user->id;
        $user = $this->getUser($uid);
        if ($user->role != ARUser::ROLE_USER) {
            self::throwError('300001');
        } else {
            $tran = Yii::$app->db->beginTransaction();
            try {
                $user->role = ARUser::ROLE_AGENT;
                $user->save();

                MessagePrompt::addPrompt('apply-broker', $user);

                $broker_scoring = new ARBrokerScoring();
                $broker_scoring->uid = $user->id;
                $broker_scoring->save();

                $tran->commit();
            } catch (\Exception $e) {
                $tran->rollBack();
                throw $e;
            }
            return true;
        }
    }

    /**
     * 查询经纪人额度
     */
    public function queryAmount()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $user = self::getUser();
        if ($user->role != ARUser::ROLE_AGENT) {
            self::throwError('300003');
        }
        $broker = ARBrokerAmount::findOne(['uid' => yii::$app->user->id, 'coin' => $this->coin]);
        $amount_remain = $broker ? $broker->amount_remain : 0;
        $amount_used = $broker ? $broker->amount_used : 0;
        return ['amount' => $amount_remain, 'broker_amount' => $amount_used];
    }

    /**
     * 设置担保额
     */
    public function setAmount()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $uid = Yii::$app->user->id;
        $row = ARAssets::findOne(['uid' => $uid, 'coin' => $this->coin]);
        list($assetFlag, $difference) = Assets::verifyCoinAmount($row, $this->amount);
        if (!$assetFlag && bccomp($difference, $row->amount_vouch, Yii::$app->params['scale'])) {
            $need = bcsub($difference, $model->amount_vouch, Yii::$app->params['scale']);
            self::throwError(null, "余币不足,需入币{$need}个");
        } else {
            $model = ARBrokerAmount::findOne(['uid' => $uid, 'coin' => $this->coin]);
            if (!$model) {
                $model = new ARBrokerAmount();
                $model->uid = $uid;
                $model->coin = $this->coin;
                $model->amount_used = 0;
            }
            if (bccomp($model->amount_used, $this->amount, Yii::$app->params['scale']) > 1) {
                self::throwError(null, "预设担保额不能小于当前担保额{$model->amount_used}");
            } else {
                $model->amount = $this->amount;
                $model->amount_remain = bcsub($model->amount, $model->amount_used, Yii::$app->params['scale']);
                if (!$model->save()) {
                    self::getErrorMessge($model);
                } else {
                    return ['uid' => $model->uid, 'amount' => $model->amount, 'amount_used' => $model->amount_used, 'amount_remain' => $model->amount_remain];
                }
            }
        }
    }

    /**
     * 获取经纪人列表
     */
    public function getLists()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $model = ARBrokerAmount::find()->joinWith(['scoring', 'certificate']);
        $model = $model->andFilterWhere([ARUserCertificate::tableName() . '.country' => $this->country]);
        $model = $model->andFilterWhere([ARUserCertificate::tableName() . '.provinces' => $this->province]);
        if ($this->amount > 0) {
            $model->andWhere(['>', 'amount_remain', $this->amount]);
        }
        if ($this->coin) {
            $model->andWhere([ARBrokerAmount::tableName() . '.coin' => $this->coin]);
        }
        $model->joinWith(['user' => function ($query) {
            if ($this->nickname) {
                $query->andWhere(['like', ARUser::tableName() . '.nickname', $this->nickname]);
            }
            if ($this->account) {
                $query->andWhere(['or', [ARUser::tableName() . '.email' => $this->account], [ARUser::tableName() . '.mobile' => $this->account]]);
            }
        }]);
        $count = $model->count();
        $data = $model->limit($this->size)->offset($this->size * ($this->page - 1))
            ->orderBy([SELF::SORT_FIELD[$this->sort] => (int) $this->sort_type, 'updated_at' => SORT_DESC])
            ->all();
        $rows = ArrayHelper::toArray($data, [
            ARBrokerAmount::className() => [
                'uid',
                'nickname'  => function ($row) {
                    //用户
                    return $row->user->nickname;
                },
                'order_num' => function ($row) {
                    //成交笔数
                    return $row->num_total;
                },
                'turnovers' => function ($row) {
                    //成交额
                    return $row->amount_total;
                },
                'rating'    => function ($row) {
                    //好评度
                    return $row->scoring ? $row->scoring->rating . '%' : '0%';
                },
                'pay_mode'  => function ($row) {
                    //支付方式
                    $mode = [];
                    foreach ($row->wallet as $value) {
                        $mode[] = $value->other_type;
                    }
                    $mode = array_unique($mode);
                    asort($mode);
                    return implode(',', $mode);
                },
                'amount'    => 'amount_remain', //经纪额度
            ],
        ]);
        return ['count' => $count, 'rows' => $rows];
    }

    /**
     * 经纪人确认收款
     */
    public function receiveMoney()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $uid = Yii::$app->user->id;
        $order = AROrder::find()->where(['id' => $this->order_id])->one();
        if (!$order) {
            self::throwError('500004');
        }
        $orderFlag = Order::verifyOrderSecufity($order);
        if (!$orderFlag) {
            self::throwError('500017');
        }
        if ($order->broker != $uid) {
            self::throwError('500101');
        } elseif ($order->status != AROrder::STATUS_BUYER_TRANSFER) {
            self::throwError('500102');
        }
        $transaction = Yii::$app->db->beginTransaction();
        try {
            $fee_total = bcadd($order->broker_charge, $order->platform_charge, Yii::$app->params['scale']);
            if ($order->type == AROrder::TYPE_IN) {
                $flag = Assets::transfer($this->order_id, Assets::TRADE_TYPE_SUPPLY, $order->opp_uid, $order->uid, $order->coin, $order->amount, $fee_total);
            } else {
                $flag = Assets::transfer($this->order_id, Assets::TRADE_TYPE_NEED, $order->uid, $order->opp_uid, $order->coin, $order->amount, $fee_total);
            }
            if ($flag) {
                $timeFlag = ReplyTime::updateOrderBrokerReceipt($this->order_id);
                if (!$timeFlag) {
                    self::throwError('500005');
                }
                $order->status = AROrder::STATUS_BROKER_RECEIVE;
                $order->security_at = Yii::$app->formatter->asTimestamp('now');
                $order->security_code = Order::getOrderSecufity($order);
                if (!$order->update()) {
                    self::throwError('500006');
                }
                $user = self::getUser();
                Chat::addSystemMessage($user, $order->id, 'confirm-receive');
                $transaction->commit();
                return true;
            }
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /**
     * 经纪人确认汇款
     */
    public function remittance()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $uid = Yii::$app->user->id;
        $order = AROrder::find()->where(['id' => $this->order_id])->one();
        if (!$order) {
            self::throwError('500004');
        }
        $orderFlag = Order::verifyOrderSecufity($order);
        if (!$orderFlag) {
            self::throwError('500017');
        }
        if ($order->broker != $uid) {
            self::throwError('500101');
        } elseif ($order->status != AROrder::STATUS_BROKER_RECEIVE) {
            self::throwError('500102');
        }
        $transaction = Yii::$app->db->beginTransaction();
        try {
            $timeFlag = ReplyTime::updateOrderBrokerTransfer($this->order_id);
            if (!$timeFlag) {
                self::throwError('500005');
            }
            $order->status = AROrder::STATUS_BROKER_TRANSFER;
            $order->security_at = Yii::$app->formatter->asTimestamp('now');
            $order->security_code = Order::getOrderSecufity($order);
            if (!$order->update()) {
                self::throwError('500006');
            }
            $user = self::getUser();
            Chat::addSystemMessage($user, $order->id, 'confirm-payment');
            $transaction->commit();
            return true;
        } catch (\Exception $e) {
            $transaction->rollBack();
            throw $e;
        }
    }

    /*
     * 更改经纪人交易笔数
     */
    public static function changeNum($broker_id, $type)
    {
        $broker_amount = ARBrokerAmount::findOne($broker_id);
        if($type == 1){
            $broker_amount->num_now = $broker_amount->num_now - 1;
            $broker_amount->num_total = $broker_amount->num_total + 1;
        }elseif($type == 2){
            $broker_amount->num_now = $broker_amount->num_now - 1;
        }
        if (!$broker_amount->update()) {
            self::getErrorMessge($broker_amount);
        }
        return true;
    }

    /*
     * 获取信任经纪人列表
     */
    public function getTrustLists()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $my_trust = ARTrustBroker::find()->where(['uid' => Yii::$app->user->id])->asArray()->all();
        $my_trust = array_column($my_trust, 'broker_id');
        $model = ARBrokerAmount::find()->joinWith(['scoring', 'trust', 'certificate']);
        $model = $model->andFilterWhere([ARUserCertificate::tableName() . '.country' => $this->country]);
        $model = $model->andFilterWhere([ARUserCertificate::tableName() . '.provinces' => $this->province]);
        $model = $model->andWhere([ARBrokerAmount::tableName() . '.uid' => $my_trust]);
        if ($this->amount > 0) {
            $model->andWhere(['>', 'amount_remain', $this->amount]);
        }
        if ($this->coin) {
            $model->andWhere([ARBrokerAmount::tableName() . '.coin' => $this->coin]);
        }
        $model->joinWith(['user' => function ($query) {
            if ($this->nickname) {
                $query->andWhere(['like', ARUser::tableName() . '.nickname', $this->nickname]);
            }
            if ($this->account) {
                $query->andWhere(['or', [ARUser::tableName() . '.email' => $this->account], [ARUser::tableName() . '.mobile' => $this->account]]);
            }
        }]);
        $count = $model->count();
        $data = $model->limit($this->size)->offset($this->size * ($this->page - 1))->orderBy([SELF::SORT_FIELD[$this->sort] => (int) $this->sort_type, 'updated_at' => SORT_DESC])->all();
        $rows = ArrayHelper::toArray($data, [
            ARBrokerAmount::className() => [
                'uid',
                'nickname'  => function ($row) {
                    //用户
                    return $row->user->nickname;
                },
                'order_num' => function ($row) {
                    //成交笔数
                    return $row->num_total;
                },
                'turnovers' => function ($row) {
                    //成交额
                    return $row->amount_total;
                },
                'rating'    => function ($row) {
                    //好评度
                    return $row->scoring ? $row->scoring->rating . '%' : '0%';
                },
                'pay_mode'  => function ($row) {
                    // 支付方式
                    $mode = [];
                    foreach ($row->wallet as $value) {
                        $mode[] = $value->other_type;
                    }
                    $mode = array_unique($mode);
                    asort($mode);
                    return implode(',', $mode);
                },
                'amount'    => 'amount_remain', //经纪额度
                'epithet'   => function ($row) {
                    return $row->trust->epithet;
                },
            ],
        ]);
        return ['count' => $count, 'rows' => $rows];

    }

    /**
     * 添加信任经纪人
     */
    public function addTrustbroker()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $broker = ARUser::findOne(['id' => $this->broker_id, 'role' => ARUser::ROLE_AGENT]);
        if (!$broker) {
            self::throwError('300003');
        }
        $has_trust = ARTrustBroker::findOne(['broker_id' => $this->broker_id, 'uid' => Yii::$app->user->id]);
        if ($has_trust) {
            self::throwError('300007');
        }
        $trust = new ARTrustBroker();
        $trust->attributes = $this->attributes;
        $trust->uid = Yii::$app->user->id;
        if (!$trust->save()) {
            self::getErrorMessge($trust);
        }
        return ['broker_id' => $broker->id];
    }

    /**
     * 删除信任经纪人
     */
    public function deleteTrustBroker()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $trust = ARTrustBroker::findOne(['id' => $this->trust_id, 'uid' => Yii::$app->user->id]);
        if (!$trust) {
            self::throwError('300008');
        }
        if (!$trust->delete()) {
            self::getErrorMessge($trust);
        }
        return ['broker_id' => $trust->broker_id];
    }

    /**
     * 更新信任经纪人信息
     */
    public function updateTrustBroker()
    {
        if (!$this->validate()) {
            self::getErrorMessge($this);
        }
        $trust = ARTrustBroker::findOne(['id' => $this->trust_id, 'uid' => Yii::$app->user->id]);
        if (!$trust) {
            self::throwError('300008');
        }
        $trust->epithet = $this->epithet;
        if (!empty($trust->dirtyAttributes)) {
            if (!$trust->update()) {
                self::getErrorMessge($trust);
            }
        }
        return ['broker_id' => $trust->broker_id];
    }
}
